#pragma once

#include "Multivector.h"

class Operations 
{
public:
	//Return the Identity given by the dimension dim
	static Multivector I(int dim);

	//pow function between to integers i**j
	static int pot(int i,int j);

	//Basis Orthogonalization Method
	static vector<Multivector> _orthogonal_basis(vector<Multivector> b);

	//Blade Factorization
	static vector<Multivector> _blade_factorization(Multivector& B);

	//Exponential of a blade
	static Multivector rotor(Multivector& M, double angle);

	//Binary String to unsigned int
	static unsigned int bin_str_to_int(string s);

	//Return the Meet between two multivectors in a determined dimension
	static Multivector meet(Multivector& a, Multivector& b, int dim);

	//Return the Join between two multivectors in a determined dimension
	static Multivector join(Multivector& a, Multivector& b, int dim);

	//Return the Delta Product between 2 multivectors
	static Multivector dp(Multivector& a, Multivector& b); 

	//Return the Outer Product between 2 multivectors
	static Multivector op(Multivector& a, Multivector& b); 

	//Return the addition of 2 multivectors
	static Multivector add(Multivector& a, Multivector& b);

	//Return the subtraction of 2 multivectors
	static Multivector sub(Multivector& a, Multivector& b);

	//Return the multiplication of 2 multivectors
	static Multivector mul(Multivector& a, double b);

	//Return the division of a multivectors and a scalar
	static Multivector div(Multivector& a, double b);

	//Return the regressive product of a multivectors and a scalar
	static Multivector rp(Multivector& a, Multivector& b);  

	//Return the Geometric Product between 2 multivectors
	static Multivector gp(Multivector& a, Multivector& b); 

	//Return the Left Contration between 2 multivectors
	static Multivector lc(Multivector& a, Multivector& b);     

	//Return the Right Contration between 2 multivectors
	static Multivector rc(Multivector& a, Multivector& b);   

	//Return the Scalar between 2 multivectors
	static double sc(Multivector& a, Multivector& b);

	//Check if 2 multivectors are equal
	static bool operator==(Multivector& a, Multivector& b);

	//Check if 2 multivectors are equal
	static bool equals(Multivector& a, Multivector& b);

	//Bitmap to binary String
	static string bitmap_to_bin_str(unsigned int);

	//Multivector Geometric Product
	static Multivector ggp(Multivector& a, Multivector& b, mat space);

	//Basis convertion
	static Multivector basis_convertion(Multivector& a, mat Q);

	//Exponential
	static Multivector ex(Multivector&);

	//Sqrt
	static Multivector sqr(Multivector&);

	//Pow
	static Multivector po(Multivector&, double);

	//Log
	static Multivector lo(Multivector&);

	//Calculate the sign of two outer product basis
	static double canonical_reordering(unsigned int,unsigned int);

	//Count the number of '1' bits in a unsigned integer
	//Also calculate the grade of a blade
	static unsigned int bit_count(unsigned int);

	//Calculate the sign of two outer product basis
	static double calc_sign (unsigned int bitmap1, unsigned int bitmap2);

	//Reverse
	Multivector rev(Multivector&);

	//Inverse
	Multivector inv(Multivector&);
};

//Return a multiplication between a Scalar and a multivector
Multivector operator*(double s, Multivector& v);
